#include "string.h"
#include "stdio.h"
#include <stdlib.h>
/* 接口库 */
#include "SpindleMotor.hpp"
#include "crc.h"

/* 工具函数  */
uint16_t spindleMotorAdjustSequence(uint16_t value) {
    if( sizeof(value) == 1){
        return value;
    }
    else
    return (value >> 8) | (value << 8);
}

/* 当前类资源 */
static struct SpindleMotorResource {
    SpindleMotor *instance;
    unsigned char spindle_packets[sizeof(SpindleMotor::RequestProtocol_t)];    //Compressor协议包
    unsigned char receive_buffer[64];     //数据接收缓冲区
    SpindleMotor::RequestProtocol_t * request_content = nullptr;  //数据请求协议包
    SpindleMotor::ResponseProtocol_t * response_content = nullptr;   //数据应答协议包

} spindle_motor_resource = {
    .instance = nullptr,
    .spindle_packets = {0},
    .receive_buffer = {0},
    .request_content = (SpindleMotor::RequestProtocol_t * ) spindle_motor_resource.spindle_packets,
    .response_content = (SpindleMotor::ResponseProtocol_t * ) spindle_motor_resource.receive_buffer,
};

/* 相关类的定义以及方法实现 */
class __SpindleAdapter : public SpindleMotor::Adapter{
    public:
        virtual bool open(void);
        virtual bool close(void);
        virtual unsigned int read(void *buffer,unsigned int size);
        virtual unsigned int write(void *buffer,unsigned int size);
};

bool __SpindleAdapter::open(void){
    printf("adapter open\r\n");
    return true;
}

bool __SpindleAdapter::close(void){
    printf("adapter close\r\n");
    return true;    
}

unsigned int __SpindleAdapter::write(void *buffer,unsigned int size){
    unsigned char * data  = (unsigned char * )buffer;
    for ( int i = 0; i < size; i++){
        printf("%02X ",data[i]);
    }
    return size;
}

unsigned int __SpindleAdapter::read(void *buffer,unsigned int size){
    unsigned int length = 0;
    unsigned char *buf = (unsigned char *)buffer;

    char hexBuffer[3] = {0};
    while ( true ) {
        unsigned char ch = getchar();
        if (ch == ' ' || ch == '\t') {
            continue;
        }
        if ( ch == '\n' ) break;
        hexBuffer[length % 2] = ch;
        if (length % 2 == 1) {
            buf[length / 2] = (unsigned char)strtol(hexBuffer, NULL, 16);
        }
        length++;
    }
    return length / 2;  // 返回接收到的字节数
}

SpindleMotor :: SpindleMotor(Adapter *adapter){
    if( adapter != nullptr ){
        this->adapter = adapter;
    }
}

SpindleMotor :: ~SpindleMotor(){}

SpindleMotor * SpindleMotor::getInstance(void){
    if( spindle_motor_resource.instance == nullptr ){
        Adapter * adapter = new __SpindleAdapter();
        if( adapter != nullptr ){
            spindle_motor_resource.instance = new SpindleMotor(adapter);
        }
    }
    return spindle_motor_resource.instance;
}

/*************************************  方法实现 **************************************/
/* 构建数据包 */
bool SpindleMotor::buildPackets(uint8_t RW,uint8_t slave_address , uint16_t access_address , uint16_t access_data){

    spindle_motor_resource.request_content->slave_address = slave_address;
    spindle_motor_resource.request_content->function_code = RW;
    spindle_motor_resource.request_content->access_address = spindleMotorAdjustSequence(access_address);
    spindle_motor_resource.request_content->access_data = spindleMotorAdjustSequence(access_data);
    spindle_motor_resource.request_content->crc = crc16((uint8_t *)spindle_motor_resource.request_content,sizeof(SpindleMotor::RequestProtocol_t) - sizeof(spindle_motor_resource.request_content->crc));
   
    return true;

}

/* 处理写入的应答数据 */
bool SpindleMotor::checkResponse(void){

    uint8_t length = 0;
    int count = 0;
    while( count < 1000 ){
        length = this->adapter->read(spindle_motor_resource.receive_buffer,0);
        if ( length > 0) break;
        count ++;
    }

    if( length > 0 && length == sizeof(SpindleMotor::RequestProtocol_t)){
        if (memcmp(spindle_motor_resource.receive_buffer, spindle_motor_resource.spindle_packets, sizeof(SpindleMotor::RequestProtocol_t)) == 0) {
            memset(spindle_motor_resource.spindle_packets,0,sizeof(spindle_motor_resource.spindle_packets));
            memset(spindle_motor_resource.receive_buffer,0,sizeof(spindle_motor_resource.receive_buffer));
            return true;
        }        
    }
    memset(spindle_motor_resource.spindle_packets,0,sizeof(spindle_motor_resource.spindle_packets));
    memset(spindle_motor_resource.receive_buffer,0,sizeof(spindle_motor_resource.receive_buffer));
    return false;
}

/**
 * @brief 处理读取的应答数据
 * @return 正常返回读取的数据,否则返回相应的错误码
 */
uint16_t SpindleMotor::processResponse(void){
    uint8_t length = 0;
    uint16_t read_value = 0;
    int count = 0;
    while( count < 10 ){
        length = this->adapter->read(spindle_motor_resource.receive_buffer,0);
        if ( length > 0) break;
        count ++;
    }
    // printf("length:%d\r\n",length);
    if( length == 0 || length != sizeof(SpindleMotor::ResponseProtocol_t)) return SpindleMotor::ResponseErrorType_LengthError;
    if( spindle_motor_resource.request_content->slave_address != spindle_motor_resource.response_content->slave_address) return SpindleMotor::ResponseErrorType_AddressError;
    if( spindle_motor_resource.request_content->function_code != spindle_motor_resource.response_content->function_code) return SpindleMotor::ResponseErrorType_FunctionError;
    if( spindle_motor_resource.response_content->crc != crc16((uint8_t *)spindle_motor_resource.response_content,sizeof(SpindleMotor::ResponseProtocol_t) - sizeof(spindle_motor_resource.response_content->crc))) return SpindleMotor::ResponseErrorType_CRCError;

    read_value = spindle_motor_resource.response_content->register_value;
    /* 清空数据缓冲区 */
    memset(spindle_motor_resource.request_content,0,sizeof(spindle_motor_resource.request_content));
    memset(spindle_motor_resource.receive_buffer,0,sizeof(spindle_motor_resource.receive_buffer));
    /* 调整端序 返回正确数据 */
    read_value = spindleMotorAdjustSequence(read_value);
    return read_value;    
}

/******************************************* 数据写入 *******************************************/

bool SpindleMotor::open() {
    if ( this->adapter == nullptr ){
        return false;
    }
    buildPackets(FunctionCode_WriteFun,SlaveAddress_DefaultAddress,RegisterAddress_RS485Function,Data_1);
    this->adapter->write(spindle_motor_resource.spindle_packets , sizeof(RequestProtocol));
    bool check_response = this->checkResponse();

    return check_response;
}

bool SpindleMotor::close() {
    return true;
}

bool SpindleMotor::addressSet(uint16_t address) {
    return true;
}

bool SpindleMotor::setSpeed(uint16_t speed) {
    return true;
}

bool SpindleMotor::stopMotor() {
    return true;
}

bool SpindleMotor::corotationMotor() {
    return true;
}

bool SpindleMotor::reversalMotor() {
    return true;
}

bool SpindleMotor::breakStop() {
    return true;
}

bool SpindleMotor::reductionSet(uint16_t reduction_ratio) {
    return true;
}

bool SpindleMotor::resetFault(uint16_t reset_status) {
    return true;
}

bool SpindleMotor::magneticSet(uint16_t pole) {
    return true;
}

bool SpindleMotor::overcurrentProtectionTimeSet(uint16_t time) {
    return true;
}

/******************************************* 数据读取 *******************************************/

uint16_t SpindleMotor::getSpeed(void) {
    return 0;
}

uint16_t SpindleMotor::getMotorStatus(void) {
    return 0;
}

uint16_t SpindleMotor::getReduction(void) {
    return 0;
}

uint16_t SpindleMotor::getRestFault(void) {
    return 0;
}

uint16_t SpindleMotor::getMagneticPairs(void) {
    return 0;
}

uint16_t SpindleMotor::getOverCurrentProtectionTime(void) {
    return 0;
}

uint16_t SpindleMotor::getAddress(void) {
    return 0;
}

uint16_t SpindleMotor::getStatus(void) {
    return 0;
}

uint16_t SpindleMotor::getCurrentValue(void) {
    return 0;
}

uint16_t SpindleMotor::getVoltageValue(void) {
    return 0;
}

uint16_t SpindleMotor::getTemperatue(void) {
    return 0;
}
